'''
Created on 1 nov 2012

@author: Lanboost
'''
import random
import math
from PIL import Image

dirs = [(math.cos(a * 2.0 * math.pi / 256),
         math.sin(a * 2.0 * math.pi / 256))
         for a in range(256)]

def noise(x, y, per, perm):
    intX, intY = int(x), int(y)
    return (surflet(intX+0, intY+0, x, y, per, perm) + surflet(intX+1, intY+0, x, y, per, perm) +
            surflet(intX+0, intY+1, x, y, per, perm) + surflet(intX+1, intY+1, x, y, per, perm))

def surflet(gridX, gridY,x, y,per, perm):
        distX, distY = abs(x-gridX), abs(y-gridY)
        polyX = 1 - 6*distX**5 + 15*distX**4 - 10*distX**3
        polyY = 1 - 6*distY**5 + 15*distY**4 - 10*distY**3
        hashed = perm[perm[int(gridX)%per] + int(gridY)%per]
        grad = (x-gridX)*dirs[hashed][0] + (y-gridY)*dirs[hashed][1]
        return polyX * polyY * grad
    
def fBm(x, y, per, octs, perm):
    val = 0
    for o in range(octs):
        val += 0.5**o * noise(x*2**o, y*2**o, per*2**o, perm)
    return val

def create(size):
    perm = range(256)
    random.shuffle(perm)
    perm += perm
    
    freq, octs, data = 1/64.0, 5, []
    for y in range(size[1]):
        for x in range(size[0]):
            data.append(fBm(x*freq, y*freq, int(size[0]*freq), octs, perm))
    im = Image.new("L", (size[0], size[1]))
    im.putdata(data, size[0], size[1])
    return im